﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Windows.Forms.DataVisualization.Charting;
using OrangePrj.Forms;

namespace OrangePrj
{
    public partial class FormMain : Form
    {
#region Поля и Свойства

        private ArrayList progresslist = new ArrayList();
        private int view = 0;
        private int miniview = 2; //2-gant 3-res 4-net
        private int currentStep;
        private string depWorkName;
        private bool depStatus = false;
        private bool fullscreen = false;
        public Project project;
        private Project tmp;
        private List<Project> projects;
        private CreateNewProjectWizard wizard;
#pragma warning disable 0649
        internal Graphics gr;
#pragma warning restore 0649
        internal Bitmap btBac;
        internal Modelling model;
        public User currentUser;

        public int CurrentStep
        {
            get
            {
                return currentStep;
            }
            set
            {
                currentStep = value;
            }
        }
        internal Project CurrentProject
        {
            get
            {
                return project;
            }
            set
            {
                project = value;
            }
        }
        internal List<Project> Projects
        {
            get
            {
                return projects;
            }
            set
            {
                projects = value;
            }
        }
        public ToolStripMenuItem StepBackToolStripMenuItem
        {
            get
            {
                return stepBackToolStripMenuItem;
            }
            set
            {
                stepBackToolStripMenuItem = value;
            }
        }
        public ToolStripButton ToolButtonBack
        {
            get
            {
                return toolButtonBack;
            }
            set
            {
                toolButtonBack = value;
            }
        }
        public ToolStripMenuItem StepForwardToolStripMenuItem
        {
            get
            {
                return stepForwardToolStripMenuItem;
            }
            set
            {
                stepForwardToolStripMenuItem = value;
            }
        }
        public ToolStripButton ToolButtonForward
        {
            get
            {
                return toolButtonForward;
            }
            set
            {
                toolButtonForward = value;
            }
        }


#endregion

#region Конструкторы
        public FormMain()
            : this(new User())
        {
        }
        public FormMain(User user)
        {
            InitializeComponent();
            
            this.currentUser = user;
            //аутентификация/////////////////////////////////////
            if (this.currentUser.IsAdmin)
            {
                this.AddNewUserToolStripMenuItem.Visible = true;
            }
            else
            {
                this.AddNewUserToolStripMenuItem.Visible = false;
            }
            /////////////////////////////////////////////////////

            project = new Project();
            projects = new List<Project>();
            currentStep = 0;
            //this.currentUser.Wizard = false;
            if (this.currentUser.Wizard == true)
            {
                wizard = new CreateNewProjectWizard(this.currentUser);
                wizard.ShowDialog();
                if (wizard.DialogResult == DialogResult.OK)
                {
                    this.project = wizard.Project;
                    this.Text = @"Orange project - " + project.Name;
                    toolStripButton1.Enabled = true;
                    //this.ChangeActiveView(0);
                    if (view == 0)
                    {
                        ChangeActiveView(1);
                    }
                    else
                    {
                        ChangeActiveView(view);
                    }

                    //////////Пошаговое редактирование////////////
                    saveTemporaryProject();
                    StepBackToolStripMenuItem.Enabled = false;
                    ToolButtonBack.Enabled = false;
                    //////////////////////////////////////////////

                }
                else
                {
                    saveToolStripButton.Enabled = false;
                    toolStripButton1.Enabled = false;
                    toolButtonDepend.Enabled = false;
                    toolButtonModifyWork.Enabled = false;
                    toolButtonDeleteWork.Enabled = false;
                }
            }
        }
#endregion
        /////////ГРИША//////////

        #region Функции работы с файлами

        #endregion

        #region Пошаговое редактирование
        private void stepForwardItem_Click(object sender, EventArgs e)
        {
            stepBackToolStripMenuItem.Enabled = true;
            toolButtonBack.Enabled = true;
            currentStep++;
            if (currentStep == projects.Count)
            {
                stepForwardToolStripMenuItem.Enabled = false;
                toolButtonForward.Enabled = false;
            }
            project = new Project(projects[currentStep - 1]);
            FillTable();
            ReDraw(true);
        }
        private void stepBackItem_Click(object sender, EventArgs e)
        {
            stepForwardToolStripMenuItem.Enabled = true;
            toolButtonForward.Enabled = true;
            currentStep--;
            project = new Project(projects[currentStep - 1]);
            if (currentStep == 1)
            {
                stepBackToolStripMenuItem.Enabled = false;
                toolButtonBack.Enabled = false;
            }
            //else
            //    stepBackToolStripMenuItem_Click(sender, e);

            FillTable();
            ReDraw(true); ;
        }
        public void saveTemporaryProject()
        {
            Project tempProject = new Project(project);
            if (projects.Count > currentStep)
            {
                projects.RemoveRange(currentStep, projects.Count - currentStep);
                stepForwardToolStripMenuItem.Enabled = false;
                toolButtonForward.Enabled = false;
            }
            projects.Add(tempProject);
            currentStep++;
            stepBackToolStripMenuItem.Enabled = true;
            toolButtonBack.Enabled = true;
            
            saveToolStripButton.Enabled = true;
            
        }
        #endregion

        #region Администрирование
        private void ChangePasswordItem_Click(object sender, EventArgs e)
        {
            ChangePasswordForm chpf = new ChangePasswordForm(this.currentUser);
            chpf.Height = 253;
            if (chpf.ShowDialog() == DialogResult.OK)
            {
                this.currentUser.Password = chpf.Password;
            }
            chpf.Close();

        }
        private void ChangeUserItem_Click(object sender, EventArgs e)
        {

            FormLogin dlg = new FormLogin();
            dlg.Height = 173;

            if (dlg.ShowDialog() == DialogResult.OK)
            {

                if (dlg.getAuthorization())
                {
                    this.currentUser = new User(dlg.userName, dlg.password, dlg.admin, false);
                    this.project = new Project();
                    if (this.currentUser.IsAdmin)
                        this.AddNewUserToolStripMenuItem.Visible = true;
                    else
                        this.AddNewUserToolStripMenuItem.Visible = false;
                    this.Text = "Orange Project";
                    FillTable();
                }
                else
                {
                    MessageBox.Show("Оперцаия смены пользователя прошла неудачно."
                        + "\nПожайлуста, введите данные корректно\nПричина: "
                        + dlg.incorrect.Text, "Orange Project",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                    ChangeUserItem_Click(sender, e);

                }
            }
        }
        private void AddNewUserItem_Click(object sender, EventArgs e)
        {
            FormAdministration administration = new FormAdministration(currentUser);
            administration.ShowDialog();
        }
        
        #endregion

        #region Проверка структуры
        private void CheckButton_Click(object sender, EventArgs e)
        {
            if (project.Name != null && project.worklist.Count > 0)
            {
                string temp = project.checkAll();
                if (temp != "")
                {
                    MessageBox.Show(temp, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    MessageBox.Show("Проект сформирован корректно.\nМожно приступать к моделированию.",
                        "Проверка прошла удачно", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                }
                project.worklist.setReverseDepWorks();
                project.setEvents();
            }
            else
            {
                MessageBox.Show("Сначала создайте проект и добавте в него работу.",
                    "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        //private bool TreeBuild(Work w, List<Work> depWorks, int count)
        //{
        //    bool check;
        //    if (count == project.worklist.Count)
        //    {
        //        return false;
        //    }
        //    foreach (Work work in depWorks)
        //    {
        //        if (work.Equals(w))
        //        {
        //            return true;
        //        }
        //    }
        //    foreach (Work work in depWorks)
        //    {
        //        count++;
        //        check = TreeBuild(w, work.DepWorks, count);
        //        if (check)
        //        {
        //            return true;
        //        }
        //    }

        //    return false;
        //}//хорошая получилась функция (с) Orange Development Team
        #endregion 

        #region Обработка горячих клавиш
        private void listWork_DoubleClick(object sender, EventArgs e)
        {
            modifyWork(sender, e);
        }
        private void SetDepends_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 'd')
                setDepends(sender, e);
        }
        #endregion

        #region Сетевой граф
        private void NetView_Click(object sender, EventArgs e)
        {
            if (view != 4 && view != 0)
                if (miniview != 4 && fullscreen == false || fullscreen == true)
                    ChangeActiveView(4);
        }
        private void NetView()
        {
            this.BackgroundImage = null;
            panelWorkProp.Visible = false;
        }
        private void NetGraf()
        {
            int width = this.ClientSize.Width - 30;
            int dy = 20 + toolStrip1.Height + menuStrip.Height;
            int dyd = dy - 10;
            int height = this.ClientSize.Height - dy;
            if (width > 0 && height > 0)
            {
                btBac = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
                Graphics gr = Graphics.FromImage(btBac);
                gr.Clear(Color.White);

                Pen pen = new Pen(Color.Red);
                gr.DrawEllipse(pen, 30, dy + 30, 50, dy + 50);

                this.Invalidate();
            }
        }
        private void miniNetGraf(object sender, EventArgs e)
        {
            groupBoxGant.Text = "Сетевой граф";
            int width = groupBoxGant.Width - 30;
            int height = groupBoxGant.Height - 50;
            Brush brush = new SolidBrush(Color.Black);
            if (width > 0 && height > 0)
            {
                btBac = new Bitmap(groupBoxGant.Width, groupBoxGant.Height);
                Graphics gr = Graphics.FromImage(btBac);

                groupBoxGant.Invalidate();
            }
        }
        #endregion

        ////////РОМА////////


    #region Операции над работами
            private void addWork(object sender, EventArgs e)
            {
                if (project.Name != null)
                {
                    FormAddWork dlg = new FormAddWork();
                    if(dlg.ShowDialog() == DialogResult.OK)
                    {
                        stepBackToolStripMenuItem.Enabled = true;
                        //считывание данных
                        project.worklist.Add(dlg.w);
                        saveTemporaryProject();
                        if (view == 0)
                            ChangeActiveView(1);
                        else
                            ChangeActiveView(view);
                    }
                }
                else
                {
                    MessageBox.Show("Сначала создайте проект.");
                }
            }
            private void modifyWork(object sender, EventArgs e)
            {
                try
                {
                    string name = listBoxMainWork.Text;
                    Work work = project.worklist.getWorkByName(name);
                    FormAddWork dialog = new FormAddWork(work);
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        project.worklist.ReplaceWork(dialog.w, work);
                        saveTemporaryProject();
                        FillTable();
                        ReDraw(true);
                    }
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void deleteWork(object sender, EventArgs e)
            {
                try
                {
                    string message = "";
                    string name = listBoxMainWork.Text;
                    Work w = project.worklist.getWorkByName(name);
                    message = project.worklist.DeleteWork(w.id);
                    if (message != "")
                    {
                        MessageBox.Show(message, "Предупреждение", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                    saveTemporaryProject();
                    listBoxMainWork.SelectedItems.Clear();
                    ChangeActiveView(view);
                    if (listBoxMainWork.SelectedItems.Count == 0)
                    {
                        toolButtonModifyWork.Enabled = false;
                        toolButtonDeleteWork.Enabled = false;
                    } else
                    {
                        toolButtonModifyWork.Enabled = true;
                        toolButtonDeleteWork.Enabled = true;
                    }
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void setDepends(object sender, EventArgs e)
            {
                try
                {
                    depStatus = true;
                    depWorkName = listBoxMainWork.Text;
                    SetDependsSimple();
                }

                catch (ArgumentOutOfRangeException)
                { }
            }
            public void SetDepWorksByInd()
            {
                foreach (Work w in project.worklist)
                {
                    List<Work> l = new List<Work>();
                    foreach (int ind in w.DepInd)
                    {
                        l.Add(project.worklist.getWorkByID(ind));
                    }
                    w.DepWorks = l;
                }
            }
            public void SetRefWorkByInd()
            {
                foreach (Work w in project.worklist)
                {
                    if (w.RefworkInd != -1)
                        w.RefWork = (Work)project.worklist.getWorkByID(w.RefworkInd);
                }
            }
    #endregion
    #region Список работ
            private void ListView(object sender, EventArgs e)
            {
                if (project.worklist.Count != 0)
                {
                    this.BackgroundImage = null;
                    panelWorkProp.Visible = true;
                    panelWorkProp.BackColor = Color.White;
                    panelWorkProp.Size = this.Size;
                    this.view = 1;
                    fullscreen = false;
                    CalcListView();
                    ReDraw(false);
                }
            }
            private void List_Click(object sender, EventArgs e)
            {
                if (view != 1 && view != 0)
                    ChangeActiveView(1);
            }    
            private void CalcListView()
            {
                double per = 0.06;
                int width = (int)(ClientSize.Width * per);
                double x1 = 0.3, x2 = 4.5, x3 = 1, x4 = 1, x5 = 2.5, x6 = 6.5;
                double perSpace = (1 - per * (x1 + x2 + x3 + x4 + x5 + x6)) / 5;
                int widthSpace = (int)(ClientSize.Width * perSpace);

                listBoxMainNumber.Width = label0.Width = (int)(x1 * width);
                checkedListBoxSimple.Width = listBoxMainNumber.Width;
                listBoxMainWork.Width = label1.Width = (int)(x2 * width);
                listBoxMainTime.Width = label2.Width = (int)(x3 * width);
                listBoxMainRes.Width = label3.Width = (int)(x4 * width);
                listBoxMainType.Width = label4.Width = (int)(x5 * width);


                listBoxMainNumber.Left = label0.Left = 0;
                listBoxMainWork.Left = label1.Left = label0.Right + widthSpace;
                listBoxMainTime.Left = label2.Left = label1.Right + widthSpace;
                listBoxMainRes.Left = label3.Left = label2.Right + widthSpace;
                listBoxMainType.Left = label4.Left = label3.Right + widthSpace;
                panelAdditionalInfo.Left = label5.Left = label4.Right + widthSpace;

                int w = panelWorkProp.Right - label5.Left;
                panelAdditionalInfo.Width = label5.Width = w;

                panelAdditionalInfo.Height = ClientSize.Height - 86;
                listBoxMainWork.Height = listBoxMainType.Height
                 = listBoxMainTime.Height = listBoxMainRes.Height
                    = listBoxMainNumber.Height = panelAdditionalInfo.Height + 16;
                groupBoxGant.Height = panelAdditionalInfo.Height - 267;
                groupBoxGant.Top = 267;
                groupBoxGant.Width = w;
            }
            public void FillTable()
            {
                this.ListView(this, null);
                listBoxMainNumber.Items.Clear();
                listBoxMainWork.Items.Clear();
                listBoxMainTime.Items.Clear();
                listBoxMainRes.Items.Clear();
                listBoxMainType.Items.Clear();
                SortWorkList();
                for (int i = 0; i < project.worklist.Count; i++)
                {
                    Work w = project.worklist[i];
                    string name = w.Name;
                    double time = w.Time;
                    double res = w.Resource.Amount;
                    WorkType type = w.Type;
                    listBoxMainNumber.Items.Add(i + 1);
                    listBoxMainWork.Items.Add(name);
                    listBoxMainTime.Items.Add(time);
                    listBoxMainRes.Items.Add(res);
                    listBoxMainType.Items.Add(type);
                }
                ReDraw(true);
            }
            private void listBoxMainWork_MouseDown(object sender, MouseEventArgs e)
            {
                try
                {
                    int ind = listBoxMainWork.SelectedIndex;
                    SelectAllPanels(ind);
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void listBoxMainTime_MouseDown(object sender, MouseEventArgs e)
            {
                try
                {
                    int ind = listBoxMainTime.SelectedIndex;
                    SelectAllPanels(ind);
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void listBoxMainType_MouseDown(object sender, MouseEventArgs e)
            {
                try
                {
                    int ind = listBoxMainType.SelectedIndex;
                    SelectAllPanels(ind);
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void listBoxMainRes_MouseDown(object sender, MouseEventArgs e)
            {
                try
                {
                    int ind = listBoxMainRes.SelectedIndex;
                    SelectAllPanels(ind);
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void VisibleCoef(Work w, int ind)
            {
                int count = project.worklist.Count;
                comboBoxBackWorkDepends.Items.Clear();

                foreach (Work wt in project.worklist)
                {
                    if (wt.hasDepends() == false)
                        wt.rank = 0;
                    else
                        wt.setMaxRank();
                }
                //labelRank.Text = w.rank.ToString();
                labelRank.Text = w.id.ToString();
                if (w.Type == WorkType.Возврат)
                {
                    textBoxChangeProb.Enabled = true;
                    textBoxChangeHard.Enabled = true;
                    textBoxProb.Enabled = true;
                    comboBoxBackWorkDepends.Enabled = true;
                    var subset = project.worklist.Where(work => work != w).OrderBy(work => work.id).Select(work => work.Name);
                    comboBoxBackWorkDepends.Items.AddRange(subset.ToArray());
                }
                else if (w.Type == WorkType.Простая)
                {
                    textBoxChangeProb.Enabled = false;
                    textBoxChangeHard.Enabled = true;
                    textBoxProb.Enabled = false;
                    comboBoxBackWorkDepends.Enabled = false;
                    comboBoxBackWorkDepends.Text = "";
                }
                else
                {
                    textBoxChangeProb.Enabled = false;
                    textBoxChangeHard.Enabled = true;
                    textBoxProb.Enabled = true;
                    comboBoxBackWorkDepends.Enabled = false;
                    comboBoxBackWorkDepends.Text = "";
                }
            }
            private void buttonSetCoef_Click(object sender, EventArgs e)
            {
                int ind = listBoxMainType.SelectedIndex;
                Work w = project.worklist.getWorkByName(listBoxMainWork.Items[ind].ToString());

                w.Probability = Convert.ToDouble(textBoxProb.Text);
                w.Ch_Prob = Convert.ToDouble(textBoxChangeProb.Text);
                w.Hard = Convert.ToDouble(textBoxChangeHard.Text);
                w.Description = textBoxDescr.Text;

                if (w.Type == WorkType.Возврат)
                {
                    int sel_ind = comboBoxBackWorkDepends.SelectedIndex + 1;
                    if (sel_ind > ind)
                        sel_ind++;
                    w.RefworkInd = sel_ind - 1;
                    w.RefWork = (Work)project.worklist.getWorkByID(w.RefworkInd);
                }
                ReDraw(true);
                saveTemporaryProject();
            }
            private void SelectAllPanels(int ind)
            {
                Work w = project.worklist[ind];

                listBoxMainWork.SetSelected(ind, true);
                listBoxMainTime.SetSelected(ind, true);
                listBoxMainType.SetSelected(ind, true);
                listBoxMainRes.SetSelected(ind, true);

                listBoxMainNumber.SelectedItems.Clear();
                foreach (int index in w.DepInd)
                {
                    Work wd = project.worklist.getWorkByID(index);
                    listBoxMainNumber.SelectedItems.Add(listBoxMainWork.Items.IndexOf(wd.Name)+1);
                }
                textBoxDescr.Text = w.Description;
                textBoxProb.Text = w.Probability.ToString();
                textBoxChangeProb.Text = w.Ch_Prob.ToString();
                textBoxChangeHard.Text = w.Hard.ToString();
                buttonSetCoef.Enabled = true;
                VisibleCoef(w, ind);
                SelectMiniView(false);
                if (depStatus == true)
                    setDepends(this, null);
                if (listBoxMainWork.SelectedItems.Count == 0)
                {
                    toolButtonModifyWork.Enabled = false;
                    toolButtonDeleteWork.Enabled = false;
                } else
                {
                    toolButtonModifyWork.Enabled = true;
                    toolButtonDeleteWork.Enabled = true;
                }
            }
            private void SortWorkList()
            {
                foreach (Work w in project.worklist)
                {
                    if (w.hasDepends() == false)
                        w.rank = 0;
                    else
                        w.setMaxRank();
                }
                project.worklist.Sort(project.useRankSortRule);
            }
            private void listBoxMainWork_KeyUp(object sender, KeyEventArgs e)
            {
                try
                {
                    if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Right || e.KeyCode == Keys.Left)
                    {
                        int ind = listBoxMainWork.SelectedIndex;
                        SelectAllPanels(ind);
                    }
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void listBoxMainTime_KeyUp(object sender, KeyEventArgs e)
            {
                try
                {
                    if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Right || e.KeyCode == Keys.Left)
                    {
                        int ind = listBoxMainTime.SelectedIndex;
                        SelectAllPanels(ind);
                    }
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void listBoxMainRes_KeyUp(object sender, KeyEventArgs e)
            {
                try
                {
                    if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Right || e.KeyCode == Keys.Left)
                    {
                        int ind = listBoxMainRes.SelectedIndex;
                        SelectAllPanels(ind);
                    }
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
            private void listBoxMainType_KeyUp(object sender, KeyEventArgs e)
            {
                try
                {
                    if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Right || e.KeyCode == Keys.Left)
                    {
                        int ind = listBoxMainType.SelectedIndex;
                        SelectAllPanels(ind);
                    }
                }
                catch (ArgumentOutOfRangeException)
                { }
            }
    #endregion
    #region Диаграмма Ганта
            private void GantMenu_Click(object sender, EventArgs e)
            {
                if (view != 2 && view !=0)
                    if (miniview !=2 && fullscreen == false || fullscreen == true)
                            ChangeActiveView(2);
            }
            private void GantView(object sender, EventArgs e)
            {
                this.BackgroundImage = null;
                panelWorkProp.Visible = false;
            }
            private void groupBoxGant_Paint(object sender, PaintEventArgs e)
            {
                if (btBac != null)
                    e.Graphics.DrawImage(btBac, 0, 0);
            }
            private void miniGant(Work w_sel, bool toCalc)
            {
                if (project.worklist.Count == 0) 
                {
                    return;
                }
                groupBoxGant.Text = "Диаграмма Ганта";
                if (toCalc == true)
                {
                    project.worklist.Ranking();
                    //временной сдвиг
                    project.worklist.RefreshWorkTime();
                }
                //отображение диаграммы
                int width = groupBoxGant.Width - 30;
                int height = groupBoxGant.Height - 50;
                int count = project.worklist.Count;
                double T = project.getPrjTime();
                double W;
                if (T==0)
                    W = width;
                else
                    W = width / T;
                double H = height / count;
                int c = 1;

                btBac = new Bitmap(groupBoxGant.Width, groupBoxGant.Height);
                Graphics gr = Graphics.FromImage(btBac);

                Pen pen = new Pen(Color.Black);
                pen.DashStyle = DashStyle.Dot;
                //отрисовка работ на диаграмме

                for (int i = 0; i <= project.worklist.getMaxRank(); i++)
                {
                    foreach (Work w in project.worklist)
                    {
                        if (w.rank == i)
                        {
                            Rectangle r = new Rectangle();
                            double t = w.timestart;
                            if (w.Type == WorkType.Возврат)
                            {
                                if (w.RefworkInd == -1)
                                {
                                    r.X = 15 + (int)(t * W);
                                    r.Y = height + 16 - (int)((c++) * H);
                                    r.Width = (int)(w.Time * W + 1);
                                }
                                else
                                {
                                    Work refwork = (Work)project.worklist.getWorkByID(w.RefworkInd);
                                    t = refwork.timestart;
                                    double time = w.timestart - t;
                                    r.X = 15 + (int)(t * W);
                                    r.Y = height + 16 - (int)((c++) * H);
                                    r.Width = (int)(time * W + 1);
                                }

                            }
                            else
                            {
                                r.X = 15 + (int)(t * W);
                                r.Y = height + 16 - (int)((c++) * H);
                                if (w.Time != 0)
                                    r.Width = (int)(w.Time * W + 1);
                                else
                                    r.Width = 5;
                            }

                            r.Height = (int)H;
                            if (r.Height != 0 & r.Width != 0)
                            {
                                Brush brush;
                                if (w.Type == WorkType.Простая)
                                {
                                    brush = new LinearGradientBrush(r, Color.GreenYellow, Color.Green, 3);
                                    gr.FillRectangle(brush, r);
                                }
                                else if (w.Type == WorkType.ИЛИ)
                                {
                                    brush = new LinearGradientBrush(r, Color.Yellow, Color.DarkOrange, 1);
                                    gr.FillRectangle(brush, r);
                                    Brush brushtext = new SolidBrush(Color.Black);
                                    Font font = new System.Drawing.Font(FontFamily.GenericSansSerif, r.Height/2);
                                }
                                else if (w.Type == WorkType.Искл_ИЛИ)
                                {
                                    brush = new LinearGradientBrush(r, Color.DodgerBlue, Color.Blue, 2);
                                    gr.FillRectangle(brush, r);
                                    Brush brushtext = new SolidBrush(Color.Black);
                                    Font font = new System.Drawing.Font(FontFamily.GenericSansSerif, r.Height/2);
                                }
                                else
                                {
                                    brush = new LinearGradientBrush(r, Color.Red, Color.Firebrick, 2);
                                    gr.FillRectangle(brush, r);
                                }
                            }
                        }
                    }
                }
                //отрисовка сетки
                for (int i = 0; i <= T; i++)
                {
                    gr.DrawLine(pen, 15 + (int)(i * W), height + 16 - (int)(count * H), 15 + (int)(i * W), height + 16);
                }
                for (int i = 0; i <= count; i++)
                {
                    gr.DrawLine(pen, 15, height + 16 - (int)(i * H), width + 15, height + 16 - (int)(i * H));
                }
                for (int i = 0; i < count; i++)
                {
                    Brush brush = new SolidBrush(Color.Black);

                    gr.DrawString((i + 1).ToString(), Font, brush, 0, height + 6 - (int)(i * H + H / 2));
                }
                //отрисовка выделения работы
                DrawFrame(w_sel, btBac, gr);
                pen.Width = 2;
                pen.DashStyle = DashStyle.Solid;
                gr.DrawLine(pen, 15, height + 16 - (int)(count * H), 15, height + 16);
                gr.DrawLine(pen, 15, height + 16, width + 15, height + 16);
                gr.DrawLine(pen, 15, height + 16 - (int)(count * H), width + 15, height + 16 - (int)(count * H));
                gr.DrawLine(pen, width + 15, height + 16 - (int)(count * H), width + 15, height + 16);

                groupBoxGant.Invalidate();
            }
            private void Gant()
            {
                int width = this.ClientSize.Width - 30;
                int dy = 20 + toolStrip1.Height + menuStrip.Height;
                int dyd = dy - 10;
                int height = this.ClientSize.Height - dy;
                int count = project.worklist.Count;
                double T = project.getPrjTime();
                double W = width / T;
                double H = height / count;
                int c = 1;
                if (width > 0 && height > 0)
                {
                    btBac = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
                    Graphics gr = Graphics.FromImage(btBac);

                    Pen pen = new Pen(Color.Black);
                    Brush brush;
                    //отрисовка работ на диаграмме
                    for (int i = 0; i <= project.worklist.getMaxRank(); i++)
                    {
                        foreach (Work w in project.worklist)
                        {
                            if (w.rank == i)
                            {

                                Rectangle r = new Rectangle();
                                Rectangle ar = new Rectangle();
                                double t;
                                t = w.timestart;
                                r.Height = (int)H;
                                if (w.Type == WorkType.Возврат)
                                {
                                    Work refwork = (Work)project.worklist.getWorkByID(w.RefworkInd);
                                    t = refwork.timestart;
                                    double time = w.timestart - t;
                                    r.X = 15 + (int)(t * W);
                                    r.Y = height + dyd - (int)((c++) * H);
                                    r.Width = (int)(time * W + 1);
                                    pen.DashStyle = DashStyle.Solid;
                                    pen.Width = 4;
                                
                                    ar.X = r.X;
                                    ar.Y = r.Y + r.Height;
                                    ar.Height = height + dyd - (int)((w.RefworkInd+1) * H) - ar.Y + 1;
                                    ar.Width = 4;
                                    if (refwork.Type == WorkType.Простая)
                                        brush = new LinearGradientBrush(ar, Color.Red, Color.GreenYellow, 45);
                                    else if (refwork.Type == WorkType.ИЛИ)
                                        brush = new LinearGradientBrush(ar, Color.Red, Color.Yellow, 45);
                                    else
                                        brush = new LinearGradientBrush(ar, Color.Red, Color.DodgerBlue, 45);
                                    gr.FillRectangle(brush, ar);
                                
                                }
                                else
                                {
                                    r.X = 15 + (int)(t * W);
                                    r.Y = height + dyd - (int)((c++) * H);
                                    if (w.Time != 0)
                                        r.Width = (int)(w.Time * W + 1);
                                    else
                                        r.Width = 5;
                                }
                            
                            
                           
                                if (w.Type == WorkType.Простая)
                                    brush = new LinearGradientBrush(r, Color.GreenYellow, Color.Green, 45);
                                else if (w.Type == WorkType.ИЛИ)
                                    brush = new LinearGradientBrush(r, Color.Yellow, Color.DarkOrange, 45);
                                else if (w.Type == WorkType.Искл_ИЛИ)
                                    brush = new LinearGradientBrush(r, Color.DodgerBlue, Color.Blue, 45);
                                else
                                    brush = new LinearGradientBrush(r, Color.Red, Color.Firebrick, 45);
                                gr.FillRectangle(brush, r);
                            
                            }
                        }
                    }
                    pen.DashStyle = DashStyle.Dot;
                    pen.Width = 1;
                    //отрисовка сетки
                    for (int i = 0; i <= T; i++)
                    {
                        gr.DrawLine(pen, 15 + (int)(i * W), height + dyd - (int)(count * H), 15 + (int)(i * W), height + dyd);
                    }
                    for (int i = 0; i <= count; i++)
                    {
                        gr.DrawLine(pen, 15, height + dyd - (int)(i * H), width + 15, height + dyd - (int)(i * H));
                    }
                    for (int i = 0; i < count; i++)
                    {
                        Brush br = new SolidBrush(Color.Black);
                        gr.DrawString((i + 1).ToString(), Font, br, 0, height + dyd - 6 - (int)(i * H + H / 2));
                    }
                    pen.Width = 2;
                    pen.DashStyle = DashStyle.Solid;
                    gr.DrawLine(pen, 15, height + dyd - (int)(count * H), 15, height + dyd);
                    gr.DrawLine(pen, 15, height + dyd, width + 15, height + dyd);
                    gr.DrawLine(pen, 15, height + dyd - (int)(count * H), width + 15, height + dyd - (int)(count * H));
                    gr.DrawLine(pen, width + 15, height + dyd - (int)(count * H), width + 15, height + dyd);

                    this.Invalidate();
                }
            }
            private void DrawFrame(Work w_sel, Bitmap btBac, Graphics gr)
            {
                int width = groupBoxGant.Width - 30;
                int height = groupBoxGant.Height - 50;
                int count = project.worklist.Count;
                double T = project.getPrjTime();
                double W = width / T;
                double H = height / count;
                int c = 1;
                for (int i = 0; i <= project.worklist.getMaxRank(); i++)
                {
                    foreach (Work w in project.worklist)
                    {
                        if (w.rank == i)
                        {
                            if (w_sel == w)
                            {
                                if (w_sel.Type != WorkType.Возврат)
                                {
                                    Rectangle rct = new Rectangle();
                                    double ts = w_sel.timestart;
                                    rct.X = 15 + (int)(ts * W);
                                    rct.Y = height + 16 - (int)(c * H);
                                    rct.Width = (int)(w_sel.Time * W);
                                    rct.Height = (int)H;
                                    Pen pencil = new Pen(Color.White, 2);
                                    gr.DrawRectangle(pencil, rct);
                                }
                                else
                                {
                                    if (w_sel.RefworkInd != -1)
                                    {
                                        Rectangle rct = new Rectangle();
                                        Work refwork = (Work)project.worklist.getWorkByID(w_sel.RefworkInd);
                                        double t = refwork.timestart;
                                        double time = w_sel.timestart - t;
                                        rct.X = 15 + (int)(t * W);
                                        rct.Y = height + 16 - (int)(c * H);
                                        rct.Width = (int)(time * W + 1);
                                        rct.Height = (int)H;
                                        Pen pencil = new Pen(Color.White, 2);
                                        gr.DrawRectangle(pencil, rct);
                                    }
                                }
                            }
                            if (w_sel != null)
                                foreach (Work wd in w_sel.DepWorks)
                                {
                                    if (wd == w)
                                    {
                                        Rectangle rct = new Rectangle();
                                        double ts = wd.timestart;
                                        rct.X = 15 + (int)(ts * W);
                                        rct.Y = height + 16 - (int)(c * H);
                                        rct.Width = (int)(wd.Time * W);
                                        rct.Height = (int)H;
                                        Pen pencil = new Pen(Color.Brown, 2);
                                        gr.DrawRectangle(pencil, rct);
                                    }
                                }
                            c++;
                        }
                    }
                }

            }
            private void buttonFullScreen_Click(object sender, EventArgs e)
            {
                fullscreen = true;
                ChangeActiveView(miniview);
            }
    #endregion
    #region Диаграмма ресурсов
            private void ResView_Click(object sender, EventArgs e)
            {
                if (view != 3 && view != 0)
                    if (miniview != 3 && fullscreen == false || fullscreen == true)
                        ChangeActiveView(3);
            }
            private void ResView()
            {
                this.BackgroundImage = null;
                panelWorkProp.Visible = false;
            }
            private void Resdiagram(object sender, EventArgs e)
            {
                int width = this.ClientSize.Width - 30;
                int dy = 20 + toolStrip1.Height + menuStrip.Height;
                int dyd = dy - 10;
                int height = this.ClientSize.Height - dy;
                if (width > 0 && height > 0)
                {
                    btBac = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
                    Graphics gr = Graphics.FromImage(btBac);

                    Pen pen = new Pen(Color.Black);
                    pen.DashStyle = DashStyle.Dot;
                    ////////////////////////////////
                    //отрисовка работ на диаграмме//
                    ////////////////////////////////
                    List<double> segments = new List<double>();
                    List<double> ResIntens = new List<double>();

                    CalcSegments(segments);

                    for (int i = 0; i < segments.Count - 1; i++)
                    {
                        double res = 0;
                        foreach (Work w in project.worklist)
                            if (w.timestart <= segments[i])
                                if (w.timeend >= segments[i + 1])
                                    res += w.Resource.Amount;

                        ResIntens.Add(res);
                    }
                    int count = (int)ResIntens.Max();
                    double T = project.getPrjTime();
                    double W = (double)width / T;
                    double H;
                    if (count != 0)
                        H = height / count;
                    else
                        H = 0;

                    for (int i = 0; i < segments.Count - 1; i++)
                    {
                        Brush brush;
                        Rectangle r = new Rectangle();
                        double t = segments[i];
                        r.Height = (int)(ResIntens[i] * H);
                        r.X = 15 + (int)(t * W);
                        r.Y = height + dyd - r.Height;
                        r.Width = (int)((segments[i + 1] - segments[i]) * W + 1);

                        if (r.Height != 0 && r.Width != 0)
                        {
                            brush = new LinearGradientBrush(r, Color.DarkRed, Color.DarkOrange, 90);
                            gr.FillRectangle(brush, r);
                        }
                    }

                    //отрисовка сетки
                    for (int i = 0; i <= T; i++)
                    {
                        gr.DrawLine(pen, 15 + (int)(i * W), height + dyd - (int)(count * H), 15 + (int)(i * W), height + dyd);
                    }
                    for (int i = 0; i <= count; i++)
                    {
                        gr.DrawLine(pen, 15, height + dyd - (int)(i * H), width + 15, height + dyd - (int)(i * H));
                    }
                    for (int i = 0; i <= count; i++)
                    {
                        Brush brush = new SolidBrush(Color.Black);
                        gr.DrawString((i).ToString(), Font, brush, 0, height + dyd - 6 - (int)((i) * H));
                    }
                    pen.Width = 2;
                    pen.DashStyle = DashStyle.Solid;
                    gr.DrawLine(pen, 15, height + dyd - (int)(count * H), 15, height + dyd);
                    gr.DrawLine(pen, 15, height + dyd, width + 15, height + dyd);
                    gr.DrawLine(pen, 15, height + dyd - (int)(count * H), width + 15, height + dyd - (int)(count * H));
                    gr.DrawLine(pen, width + 15, height + dyd - (int)(count * H), width + 15, height + dyd);

                    double minres = MinRes();
                    pen.Color = Color.Lime;
                    pen.Width = 4;
                    pen.DashStyle = DashStyle.Dash;
                    gr.DrawLine(pen, 15, height + dyd - (int)(minres * H), width + 15, height + dyd - (int)(minres * H));

                    this.Invalidate();
                }
            }
            private void miniResdiagram(object sender, EventArgs e)
            {
                try
                {
                    groupBoxGant.Text = "Гистограмма ресурсопотребления";
                    int width = groupBoxGant.Width - 30;
                    int height = groupBoxGant.Height - 50;

                    if (width > 0 && height > 0)
                    {
                        btBac = new Bitmap(groupBoxGant.Width, groupBoxGant.Height);
                        Graphics gr = Graphics.FromImage(btBac);

                        Pen pen = new Pen(Color.Black);
                        pen.DashStyle = DashStyle.Dot;
                        ////////////////////////////////
                        //отрисовка работ на диаграмме//
                        ////////////////////////////////
                        List<double> segments = new List<double>();
                        List<double> ResIntens = new List<double>();

                        CalcSegments(segments);

                        for (int i = 0; i < segments.Count - 1; i++)
                        {
                            double res = 0;
                            foreach (Work w in project.worklist)
                                if (w.timestart <= segments[i])
                                    if (w.timeend >= segments[i + 1])
                                        res += w.Resource.Amount;

                            ResIntens.Add(res);
                        }
                        int count = (int)ResIntens.Max();
                        double T = project.getPrjTime();
                        double W = (double)width / T;
                        double H = height / count;
                        int dyd = 16;
                        for (int i = 0; i < segments.Count - 1; i++)
                        {
                            Brush brush;
                            Rectangle r = new Rectangle();
                            double t = segments[i];
                            r.Height = (int)(ResIntens[i] * H);
                            r.X = 15 + (int)(t * W);
                            r.Y = height + dyd - r.Height;
                            r.Width = (int)((segments[i + 1] - segments[i]) * W + 1);

                            if (r.Height != 0 && r.Width != 0)
                            {
                                brush = new LinearGradientBrush(r, Color.DarkRed, Color.DarkOrange, 90);
                                gr.FillRectangle(brush, r);
                            }
                        }

                        //отрисовка сетки
                        for (int i = 0; i <= T; i++)
                        {
                            gr.DrawLine(pen, 15 + (int)(i * W), height + dyd - (int)(count * H), 15 + (int)(i * W), height + dyd);
                        }
                        for (int i = 0; i <= count; i++)
                        {
                            gr.DrawLine(pen, 15, height + dyd - (int)(i * H), width + 15, height + dyd - (int)(i * H));
                        }
                        for (int i = 0; i <= count; i++)
                        {
                            Brush brush = new SolidBrush(Color.Black);
                            gr.DrawString((i).ToString(), Font, brush, 0, height + dyd - 6 - (int)((i) * H));
                        }
                        pen.Width = 2;
                        pen.DashStyle = DashStyle.Solid;
                        gr.DrawLine(pen, 15, height + dyd - (int)(count * H), 15, height + dyd);
                        gr.DrawLine(pen, 15, height + dyd, width + 15, height + dyd);
                        gr.DrawLine(pen, 15, height + dyd - (int)(count * H), width + 15, height + dyd - (int)(count * H));
                        gr.DrawLine(pen, width + 15, height + dyd - (int)(count * H), width + 15, height + dyd);

                        double minres = MinRes();
                        pen.Color = Color.Lime;
                        pen.Width = 4;
                        pen.DashStyle = DashStyle.Dash;
                        gr.DrawLine(pen, 15, height + dyd - (int)(minres * H), width + 15, height + dyd - (int)(minres * H));

                        groupBoxGant.Invalidate();
                    }
                }
                catch (Exception ex)
                { }
            }
            private void CalcSegments(List<double> segments)
            {
                segments.Clear();
                foreach (Work w in project.worklist)
                {
                    segments.Add(w.timestart);
                    segments.Add(w.timeend);
                }
                RemoveDuplex(segments);
                segments.Sort();
            }
            private void RemoveDuplex(List<double> segments)
            {
                bool stat = true;
                while (stat == true)
                {
                    if (segments.Count == 0)
                        stat = false;

                    foreach (double d1 in segments)
                    {
                        int count = 0;
                        foreach (double d2 in segments)
                        {
                            if (d1 == d2)
                                count++;
                        }
                        for (int i = 1; i < count; i++)
                        {
                            segments.Remove(d1);
                        }
                        if (count > 1)
                            break;
                        if (segments[segments.Count - 1] == d1)
                            stat = false;
                    }
                }
            }
            private double MinRes()
            {
                double res=0;
                foreach (Work w in project.worklist)
                    if (w.Resource.Amount > res)
                        res = w.Resource.Amount;
                return res;
            }
    #endregion
    #region Общая прорисовка
            public void ChangeActiveView(int view)
            {
                SortWorkList();
                if (view == 0)
                {
                    this.view = 0;
                    emptyView();
                }
                else if (view == 1)
                {
                    this.view = 1;
                    FillTable();
                }
                else if (view == 2)
                {
                    if (fullscreen == true)
                    {
                        this.view = 2;
                        GantView(this, null);
                        Gant();
                    }
                    else
                    {
                        miniview = 2;
                        int ind = listBoxMainWork.SelectedIndex;
                        if (ind == -1)
                            miniGant(null, false);
                        else
                        {
                            Work w = (Work)project.worklist[ind];
                            miniGant(w, false);
                        }
                    }
                }
                else if (view == 3)
                {
                
                    if (fullscreen == true)
                    {
                        this.view = 3;
                        ResView();
                        Resdiagram(this, null);
                    }
                    else
                    {
                        miniview = 3;
                        SelectMiniView(false);
                    }
                }
                else if (view == 4)
                {
                    if (fullscreen == true)
                    {
                        this.view = 4;
                        NetView();
                        NetGraf();
                    }
                    else
                    {
                        miniview = 4;
                        SelectMiniView(false);
                    }
                }
            
            }
            public void ReDraw(bool toCalc)
            {
                if (view == 1)
                    SelectMiniView(toCalc);
                if (view == 2)
                    Gant();
                if (view == 3)
                    Resdiagram(this, null);
                if (view == 4)
                    NetGraf();       
            }
            private void FormMain_Paint(object sender, PaintEventArgs e)
            {
                if (view != 0 && view !=1)
                    if (btBac != null)
                        e.Graphics.DrawImage(btBac, 0, 0);
            }
            private void FormMain_SizeChanged(object sender, EventArgs e)
            {
                if (view == 1)
                {
                    panelWorkProp.Size = this.Size;
                    CalcListView();        
                }
                ReDraw(true);
            }
            private void emptyView()
            {
                this.BackgroundImage = Properties.Resources.orange2;
                panelWorkProp.Visible = false;
            }
            private void SelectMiniView(bool toCalc)
            {
                if (miniview == 2)
                {
                    int ind = listBoxMainWork.SelectedIndex;
                    if (ind == -1)
                        miniGant(null, toCalc);
                    else
                    {
                        Work w = (Work)project.worklist[ind];
                        miniGant(w, toCalc);
                    }
                }
                if (miniview == 3)
                {
                    miniResdiagram(this, null);
                }
                if (miniview == 4)
                {
                    miniNetGraf(this, null);
                }
            }
    #endregion
    #region Зависимости
            private void SetDependsSimple()
            {
                try
                {

                    Work w = project.worklist.getWorkByName(depWorkName);
                    List<int> depInd_old;
                    int count = project.worklist.Count;

                    checkedListBoxSimple.Items.Clear();
                    for (int i = 0; i < count; i++)
                    {
                        checkedListBoxSimple.Items.Add("");

                        if (depWorkName == listBoxMainWork.Items[i].ToString())
                            checkedListBoxSimple.SetItemCheckState(i, CheckState.Indeterminate);
                    }

                    depInd_old = w.DepInd;

                    foreach (int i in depInd_old)
                    {
                        checkedListBoxSimple.SetItemChecked(listBoxMainWork.Items.IndexOf(project.worklist.getWorkByID(i).Name), true);
                    }

                    checkedListBoxSimple.Visible = true;
                    buttonDepSimpleSET.Visible = true;
                    buttonDepSimpleCancel.Visible = true;
                    listBoxMainNumber.Visible = false;
                }
                catch (NullReferenceException ex)
                {
                    MessageBox.Show("Сначала выберите работу");
                }
            }
            private void buttonDepSimpleCancel_Click(object sender, EventArgs e)
            {
                buttonDepSimpleCancel.Visible = false;
                buttonDepSimpleSET.Visible = false;
                checkedListBoxSimple.Visible = false;
                listBoxMainNumber.Visible = true;
                depStatus = false;
            }
            private void buttonDepSimpleSET_Click(object sender, EventArgs e)
            {
                Work w = project.worklist.getWorkByName(depWorkName);
                int count = project.worklist.Count;
                List<int> depInd_new = new List<int>();
                List<Work> depWorks = new List<Work>();

                for (int i = 0; i < count; i++)
                {
                    if (depWorkName != listBoxMainWork.Items[i].ToString())
                        if (checkedListBoxSimple.GetItemChecked(i) == true)
                        {
                            int id = project.worklist.getIdByWorkName(listBoxMainWork.Items[i].ToString());
                            depInd_new.Add(id);
                            depWorks.Add(project.worklist.getWorkByID(id));
                        }
                }

                if (project.TreeBuild(w, depWorks, 0))
                {
                    MessageBox.Show("Нельзя установить зависимость таким образом.\n" +
                        "Образуется цикл.", "Ошибка.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    w.DepInd = depInd_new;
                    w.DepWorks = depWorks;
                    saveTemporaryProject();
                    ReDraw(true);
                }
                FillTable();
            }
    #endregion
    #region Моделирование

        private void startModelling(object sender, EventArgs e)
        {
            FormModelView modelview = new FormModelView(this.project);
            modelview.Show();
            //ProjectBack(sender, e);
            //Modelling model = new Modelling(this.project);
            //model.Run();
        }
        private void ProjectBack(object sender, EventArgs e)
        {
            if (tmp != null)
                project = (Project)tmp.Clone();

            ChangeActiveView(view);
        }

    #endregion

        private void CreateNewProject_Click(object sender, EventArgs e)
        {
            using (FormNewPrj prjcreator = new FormNewPrj())
            {
                if (prjcreator.ShowDialog() == DialogResult.OK)
                {
                    project = new Project(prjcreator.Name, prjcreator.Description, currentUser);
                }
            }
            
        }

        private void OpenProject_Click(object sender, EventArgs e)
        {
            String errorMessage;
            Project tempProject;
            if ((tempProject = FileReader.Open(currentUser, out errorMessage)) != null)
            {
                project = tempProject;
                FillTable();
            }
            else
            {
                MessageBox.Show(errorMessage, "Ошибка при чтении из файла", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void SaveProject_Click(object sender, EventArgs e)
        {
            FileReader.Save(project);
        }
    }
}